﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Moon.Sql
{
    public abstract partial class Repository<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity : class
    {
        public async Task<int> InsertAsync(TEntity entity)
        {
            return await Context.Insertable<TEntity>(entity).ExecuteAsync();
        }

        public async Task<int> InsertAsync(List<TEntity> list)
        {
            return await Context.Insertable<TEntity>(list).ExecuteAsync();
        }

        public async Task<long> InsertGetIdentityAsync(TEntity entity)
        {
            return await Context.Insertable<TEntity>(entity).ExecuteIdentityAsync();
        }

        public async Task<int> DeleteAsync(TEntity entity)
        {
            var array = MapperTable.Properties.Where(i => i.IsPrimaryKey);
            if (array != null && array.Count() == 1)
            {
                PropertyMap propertyMap = array.FirstOrDefault();
                return await Context.Deleteable<TEntity>(propertyMap.PropertyInfo.GetValue(entity)).ExecuteAsync();
            }
            else
            {
                throw new Exception("primary key is empty or has more than one primary key");
            }
        }

        public async Task<int> DeleteAsync(Expression<Func<TEntity, bool>> where)
        {
            return await Context.Deleteable<TEntity>().Where(where).ExecuteAsync();
        }

        public async Task<int> DeleteAsync(params TKey[] pks)
        {
            return await Context.Deleteable<TEntity>(pks).ExecuteAsync();
        }

        public async Task<int> UpdateAsync(TEntity entity, Expression<Func<TEntity, bool>> where)
        {
            return await Context.Updateable<TEntity>(entity).Where(where).ExecuteAsync();
        }

        public async Task<int> UpdateAsync(TEntity entity, Expression<Func<TEntity, object>> columns, Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, object>> ignoreColumns = null)
        {
            return await Context.Updateable<TEntity>(entity).SetColumns(columns).IgnoreColumns(ignoreColumns).Where(where).ExecuteAsync();
        }

        public async Task<List<TEntity>> GetListAsync()
        {
            return await Context.Queryable<TEntity>().ToListAsync();
        }

        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> where)
        {
            return await Context.Queryable<TEntity>().Where(where).ToListAsync();
        }

        public async Task<QueryPageResult<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> where, int offset, int limit)
        {
            return await Context.Queryable<TEntity>().Where(where).ToPageListAsync<TEntity>(offset, limit);
        }

        public async Task<QueryPageResult<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> where, int offset, int limit, Expression<Func<TEntity, object>> orderField, OrderBy orderBy = Moon.Sql.OrderBy.Asc)
        {
            return await Context.Queryable<TEntity>().Where(where).OrderBy(orderField).ToPageListAsync<TEntity>(offset, limit);
        }

        public async Task<int> DeleteByIdAsync(TKey id)
        {
            return await Context.Deleteable<TEntity>(id).ExecuteAsync();
        }

        public async Task<TEntity> GetByIdAsync(TKey id)
        {
            return await Context.Queryable<TEntity>().FirstAsync(id);
        }

        public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> where)
        {
            return await Context.Queryable<TEntity>().Where(where).FirstAsync();
        }
    }
}
